package com.jackrain.nea.shiro.stateless;

import com.jackrain.nea.util.WebUtils;
import com.jackrain.nea.web.query.QueryEngine;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Created by Lucky dog on 2016/7/19.
 */

@Slf4j
@Component
public  class StatelessRealm extends AuthorizingRealm {

    public boolean supports(AuthenticationToken token) {
        //仅支持StatelessToken类型的Token
        return token instanceof StatelessToken;
    }
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        StatelessToken statelessToken = (StatelessToken) token;
        String accessKey = statelessToken.getPrincipal();
        String accessSecret = (String) QueryEngine.getInstance().doQueryOne(
                "select `accesssecret` from `clientaccredit`  where `accesskey`=?",new Object[]{accessKey});
        //在服务器端生成客户端参数消息摘要

        String info = accessKey + accessSecret + ((StatelessToken) token).getDateTime();
        String serverDigest = null;
        try {
            MessageDigest  messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.update(info.getBytes("UTF8" ));
            byte[] s = messageDigest.digest();
            serverDigest = WebUtils.convertToHexString(s);
        } catch (NoSuchAlgorithmException e) {
            log.error(e.getMessage(),e);
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage(),e);
        }
        //然后进行客户端消息摘要和服务器端消息摘要的匹配
        return new SimpleAuthenticationInfo(
                accessKey,
                serverDigest,
                getName());
    }

}